﻿using DataConverter.Utils;
using QDAS;
using QDasConverter;
using System.Text;

namespace DataConverter.Core
{
    /// <summary>
    /// 马头转换器。
    /// </summary>
    public class C2021T02_cvinet : ConvertBase
    {
        // 用于读取和处理Catalog数据
        QCatalog catlog = new QCatalog();

        //  每个元素为字符串数据，内容为： 工位名称，工位索引，Spindle和Spindle索引号, 提取规则为 工位名称和Spindel名称一致，然后提取 Spindle索引号。
        List<string[]> opindices = new List<string[]>();

        // 用于存储从配置中获取的读取上下限
        Dictionary<string, string[]> limits = new Dictionary<string, string[]>();

        // 用于存储从配置中获取的工位名称
        Dictionary<string, string> opNames = new Dictionary<string, string>();

        // 默认的 K2001和K2022信息
        string[] k2001s = new string[] { "FinalTorque", "FinalAngle", "FinalCurrent", "FinalTorqueRate" };
        string[] k2002s = new string[] { "扭矩", "角度", "电流", "扭矩率" };

        public C2021T02_cvinet()
        {
            CompanyName = "马头转换器";
            TableName = "RESULT";
            TableIDName = "RES_ID";
            Version = "beta0.1.0 Released Date: 2021/11/09 Inner Name: C2021T02_cvinet";
            Version = "beta0.1.1 Released Date: 2021/11/09 Inner Name: C2021T02_cvinet";
            Version = "beta0.1.2 Released Date: 2021/11/15 Inner Name: C2021T02_cvinet";

            // DebugMode
            DebugMode = true;
        }

        public override bool OnStart()
        {
            if (DebugMode)
            {
                SqlConnectionString = "Data Source = 112.74.87.167;Initial Catalog = cvinet;User ID = sa; Password = root00;";
                sm = new SQLManager(SqlConnectionString);
            }

            catlog = QCatalog.load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "configs/CATALOG.dfd"));

            // 2021/12/30 临时为了测试才加入的。
            string[] data = { "工位号,OP索引号,轴号,拧紧机索引号", "RC-0010,1110010,1,1110005", "DCT-0080,1120080,1,1110010", "DCT-0090,1120090,1,1110015", "DCT-0090,1120090,2,1110020", "DCT-0100,1120100,1,1110025", "DCT-0110,1120110,1,1110030", "DCT-0220,1120220,1,1110035", "DCT-0225,1120225,1,1110040", "DCT-0225,1120225,2,1110045", "DCT-0250,1120250,1,1120011", "DCT-0250,1120250,2,1120012", "DCT-0250,1120250,3,1120013", "DCT-0260,1120260,1,1120021", "DCT-0260,1120260,2,1120022", "DCT-0260,1120260,3,1120023", "DCT-0265,1120265,1,1110050", "DCT-0265,1120265,2,1110055", "DCT-0280,1120280,1,1110060", "DCT-0280,1120280,2,1110065", "DCT-0300,1120300,1,1110070", "DCT-0300,1120300,2,1110075", "DCT-0305,1120305,1,1110080", "DCT-0310,1120310,1,1120031", "DCT-0310,1120310,2,1120032", "DCT-0310,1120310,3,1120033", "DCT-0310,1120310,4,1120041", "DCT-0310,1120310,5,1120042", "DCT-0310,1120310,6,1120043", "DCT-0320,1120320,1,1120051", "DCT-0320,1120320,2,1120052", "DCT-0320,1120320,3,1120053", "DCT-0330,1120330,1,1110085", "DCT-0330,1120330,2,1110090", "DCT-0390,1120390,1,1110095", "DCT-0420,1120420,1,1110100", "DCT-0440,1120440,1,1120061", "DCT-0440,1120440,2,1120062", "DCT-0440,1120440,3,1120063", "DCT-0445,1120445,1,1110105", "DCT-0460,1120460,1,1120071", "DCT-0460,1120460,2,1120072", "DCT-0460,1120460,3,1120073", "DCT-0460,1120460,4,1120074", "DCT-0465,1120465,1,1110110", "DCT-0466,1120466,1,1110115", "DCT-0466,1120466,2,1110120", "DCT-0490,1120490,1,1110125", "DCT-0490,1120490,2,1110130", "MID-0110,1140110,1,1120081", "MID-0110,1140110,2,1120082", "MID-0120,1140120,1,1110135", "DIFF-0100,1130100,1,1120091", "DIFF-0100,1130100,2,1120092", "DIFF-0100,1130100,3,1120101", "DIFF-0100,1130100,4,1120102", "DIFF-0110,1130110,1,1110140", "DCT-0540,1120540,1,1110145", "DCT-0635,1120635,1,1110150", "DCT-0636,1120636,1,1110155", "DCT-0638,1120638,1,1110160" };
            foreach (var item in data)
                opindices.Add(item.Split(','));

            // 2021/12/31 临时加入为了显示上下公差
            string[] data1 = { "1110005:10,12,N·m,0,90,°", "1110010:26,30,N·m,0,90,°", "1110015:10,12,N·m,0,90,°", "1110025:10,12,N·m,0,90,°", "1110030:10,12,N·m,0,90,°", "1110035:10,12,N·m,0,90,°", "1110040:10,12,N·m,0,90,°", "1110045:20,24,N·m,0,90,°", "1120011:20,24,N·m,0,90,°", "1120021:30,34,N·m,0,90,°", "1110050:30,34,N·m,0,90,°", "1110060:22,26,N·m,0,90,°", "1110065:10,12,N·m,0,90,°", "1110070:30,34,N·m,0,90,°", "1110080:30,34,N·m,0,90,°", "1120031:30,34,N·m,0,90,°", "1120051:20,24,N·m,0,90,°", "1110085:22,26,N·m,0,90,°", "1110090:30,34,N·m,0,90,°", "1110095:10,12,N·m,0,90,°", "1110100:43,47,N·m,0,90,°", "1120061:10,12,N·m,0,90,°", "1110105:10,12,N·m,0,90,°", "1120071:10,12,N·m,0,90,°", "1110110:10,12,N·m,0,90,°", "1103030:10,12,N·m,0,90,°", "1103031:20,24,N·m,0,90,°", "1110125:14,18,N·m,0,90,°", "1120081:114,126,N·m,0,90,°", "1110135:114,126,N·m,0,90,°", "1120091:85,95,N·m,0,90,°", "1120093:85,95,N·m,0,90,°", "1110145:10,12,N·m,0,90,°", "1110150:13,17,N·m,0,90,°", "1110155:30,40,N·m,0,90,°", "1110160:20,24,N·m,0,90,°" };
            foreach (var item in data1)
                limits.Add(item.Split(':')[0], item.Split(':')[1].Split(','));


            // 2022/01/10 添加的OP信息，OP信息来自于 https://docs.qq.com/sheet/DWVBJbWtIelZhZFNz?tab=BB08J2
            var op_strs = new string[] {"ID,OP Name","1,DCT-0440","2,MID-0110","3,DCT-0260","4,DCT-0320","5,","6,DIFF-0100","7,DCT-0310","8,DCT-0310","9,DCT-0460",
                "10,DIFF-0100","11,MID-0120","12,DCT-0225","13,DCT-0330","14,DCT-0330","15,DCT-0110","16,DCT-0300","17,DCT-0220","18,DCT-0280","19,DCT-0260",
                "20,DCT-0225","21,DCT-0100","22,DCT-0635","23,DCT-0080","24,DCT-0490","25,DCT-0390","26,","27,DCT-0300","28,DCT-0540","29,DCT-0490","30,",
                "31,DCT-0638","32,DCT-0270","33,DCT-0090","34,DCT-0420","35,DIFF-0110","36,DCT-0636","37,DCT-0490","38,DCT-0280","39,DCT-0300","40,",
                "41,DCT-0420","42,DCT-0390","43,DCT-0100","44,DCT-0090","45,MID-0120","46,DCT-0080","47,DCT-0110","48,DCT-0090","49,DCT-0330","50,","51,DIFF-0110",
                "52,DCT-0270","53,DCT-0225","54,DCT-0540","55,DCT-0225","56,DCT-0260","57,DCT-0635","58,DCT-0636","59,DCT-0638",
                "60,DCT-0300","61,","62,","63,"};
            foreach (var item in op_strs)
            {
                var strs = item.Split(',');
                if (strs.Length == 2 && !opNames.ContainsKey(strs[0]))
                    opNames.Add(strs[0], strs[1]);
            }

            LoadBenchNames();
            return base.OnStart();
        }

        /// <summary>
        /// 加载工位号
        /// </summary>
        /// <param name="configfile"></param>
        private void LoadBenchNames(string configfile = "bench_names.txt")
        {
            configfile = Path.GetFullPath(configfile);
            List<string> names = new List<string>();
            List<string> texts = new List<string>();
            List<string> ips = new List<string>();

            if (!File.Exists(configfile))
                return;

            foreach (var row in File.ReadAllLines(configfile))
            {
                if (row.Length == 0)
                    continue;

                var strs = row.Trim().Replace('，', ',').Split(',');
                for (int i = 0; i < strs.Length; i++)
                    strs[i] = strs[i].Trim();
                if (strs.Length >= 2 && strs[0].Length > 0 && strs[1].Length > 0)
                {
                    names.Add(strs[0]);
                    texts.Add(strs[1]);
                    texts.Add(strs.Length > 2 ? strs[3] : "0.0.0.0");
                }
            }
        }

        /// <summary>
        /// 循环处理数据
        /// </summary>
        public override void OneLoop_Process()
        {
            LastResID= LastResID < 48500001 ? 48500001 : LastResID;
            // BatchCount=10;
            sm.CommandText = $@"SELECT   
        dbo.RESULT.RES_ID,
        dbo.CONTROLLER.CTRL_Name AS K1001, 
        dbo.RESULT.RES_FinalTorque, 
        dbo.RESULT.RES_FinalAngle, 
        dbo.RESULT.RES_FinalCurrent, 
        dbo.RESULT.RES_FinalTorqueRate, 
        dbo.RESULT.RES_DateTime AS K0004, 
        dbo.RESULT.RES_VIN AS K0014, 
        dbo.TOOL.TOOL_SerialNumber AS K0012, 
        dbo.TIGHTENING_UNIT.TU_Name AS K0009, 
        dbo.RESULT.RES_ResultNumber, 
		dbo.RESULT.RES_SpindleNumber,
        dbo.CONTROLLER.CTRL_ID AS OP_ID,
        dbo.CURVE.CRV_PointDuration, 
        dbo.CURVE.CRV_PointCount, 
        dbo.CURVE.CRV_Points
FROM    dbo.RESULT INNER JOIN
        dbo.CONTROLLER ON dbo.RESULT.RES_ControllerId = dbo.CONTROLLER.CTRL_ID INNER JOIN
        dbo.TOOL ON dbo.RESULT.RES_ToolId = dbo.TOOL.TOOL_ID INNER JOIN
        dbo.TIGHTENING_UNIT ON dbo.RESULT.RES_TuId = dbo.TIGHTENING_UNIT.TU_ID LEFT OUTER JOIN
        dbo.CURVE ON dbo.RESULT.RES_ID = dbo.CURVE.CRV_ResultID
WHERE   dbo.RESULT.RES_ID between {LastResID} and {LastResID + BatchCount}
ORDER BY dbo.RESULT.RES_ID"; // 为了提高效率，使用了基于Res_ID的 between-and 语法

            var data = sm.GetStringsEX();
            if (data == null || data.Length == 0)
            {
                Console.WriteLine("Data.length=0, return.");
                return;
            }

            // 用于保存DFQ数据文件
            Dictionary<string, QFile> opFiles = new Dictionary<string, QFile>();

            foreach (var row in data)
            {
                try
                {
                    // 00. RESULT.RES_ID,
                    // 01. CONTROLLER.CTRL_Name AS K1001, 
                    // 02. RESULT.RES_FinalTorque, 
                    // 03. RESULT.RES_FinalAngle, 
                    // 04. RESULT.RES_FinalCurrent, 
                    // 05. RESULT.RES_FinalTorqueRate, 
                    // 06. RESULT.RES_DateTime AS K0004, 
                    // 07. RESULT.RES_VIN AS K0014, 
                    // 08. TOOL.TOOL_SerialNumber AS K0012, 
                    // 09. TIGHTENING_UNIT.TU_Name AS K0009, 
                    // 10. RESULT.RES_ResultNumber, 
                    // 11. RESULT.RES_SpindleNumber
                    // 12. CONTROLLER.CTRL_ID AS OP_ID     # 2022/01/10 加入 为匹配OPName
                    // 13. dbo.CURVE.CRV_PointDuration,    # 2022/01/23 加入，用于处理曲线信息，14-15相同
                    // 14. dbo.CURVE.CRV_PointCount,
                    // 15. dbo.CURVE.CRV_Points

                    var list = new List<double>();
                    var t_delta = double.Parse(row[13]) / int.Parse(row[14]);
                    // 用于存储文件名。
                    var filenames = new List<string>();
                    // 曲线不为空时，进行相应的处理。
                    if (row[15].StartsWith("System.Object:"))
                    {
                        var key = row[15].Split(':')[1];
                        var value = new byte[1024];// sm.NonStringData[key];

                        if (value != null && value is byte[] bts)
                        {
                            StringBuilder sb = new StringBuilder();
                            for (int i = 0; i < bts.Length; i++)
                                sb.Append(bts[i].ToString("X2"));
                            var s = sb.ToString();

                            for (int i = 0; i < s.Length / 72; i++)
                            {
                                var start = i * 72;
                                var s0 = s.Substring(start, 4);
                                var s1 = s.Substring(start + 4, 16);
                                var s2 = s.Substring(start + 20, 16);
                                var s3 = s.Substring(start + 36, 16);
                                var s4 = s.Substring(start + 52, 16);
                                list.Add(i);
                                list.Add(t_delta * i);
                                list.Add(Convert1(s1));
                                list.Add(Convert1(s2));
                                list.Add(Convert1(s3));
                                list.Add(Convert1(s4));

                            } 

                            var testtime = DateTime.Parse(row[6]);
                            // 四条曲线分别为： 扭矩 (N.m);角度 (Deg); 未知; 电流 (A)
                            var curvefilename1 = $"02_{testtime:yyyyMMddHHmmss}_01_{random.NextDouble() * 1000000:0}";
                            var curvefilename2 = $"02_{testtime:yyyyMMddHHmmss}_02_{random.NextDouble() * 1000000:0}";
                            var curvefilename3 = $"02_{testtime:yyyyMMddHHmmss}_03_{random.NextDouble() * 1000000:0}";
                            var curvefilename4 = $"02_{testtime:yyyyMMddHHmmss}_04_{random.NextDouble() * 1000000:0}";

                            filenames.Add(curvefilename1);
                            filenames.Add(curvefilename2);
                            filenames.Add(curvefilename3);
                            filenames.Add(curvefilename4);

                            StringBuilder sb1 = new StringBuilder();
                            StringBuilder sb2 = new StringBuilder();
                            StringBuilder sb3 = new StringBuilder();
                            StringBuilder sb4 = new StringBuilder();
                            for (int i = 0; i < list.Count / 6; i++)
                            {
                                sb1.Append($"{list[i * 6 + 1]},{list[i * 6 + 2]};");
                                sb2.Append($"{list[i * 6 + 1]},{list[i * 6 + 3]};");
                                sb3.Append($"{list[i * 6 + 1]},{list[i * 6 + 4]};");
                                sb4.Append($"{list[i * 6 + 1]},{list[i * 6 + 5]};");
                            }

                            File.WriteAllText(Path.Combine(OutputDirectory, curvefilename1 + ".txt"), sb1.ToString());
                            Console.WriteLine("Curve file saved: " + Path.Combine(OutputDirectory, curvefilename1 + ".txt"));
                            File.WriteAllText(Path.Combine(OutputDirectory, curvefilename2 + ".txt"), sb2.ToString());
                            Console.WriteLine("Curve file saved: " + Path.Combine(OutputDirectory, curvefilename2 + ".txt"));
                        }
                    }

                    //  row[1]; 2022/01/13 由于张总无法从数据库中找到相应信息，所以为了演示临时写死。
                    string k1001 = "DF727-Temp";
                    var dt = DateTime.Parse(row[6]);
                    string k0014 = row[7];
                    string k0012 = row[8];
                    string k0009 = row[9];
                    string result_number = row[10];
                    string spindleNumber = row[11];
                    string ctrl_id = row[12];

                    // 根据Controller.CTRL_ID从ops中获得OP Name，再通过catalog获得OP编号
                    string op_name = opNames.ContainsKey(ctrl_id) ? op_name = opNames[ctrl_id] : "";
                    // 2021-12-29 加入用于提取K0100，
                    string k0100 = GetK0100(k1001, spindleNumber);
                    // "1110010:26,30,N·m,0,90,°"
                    string[] values = limits.ContainsKey(k0100) ? limits[k0100] : new string[6];

                    QFile qf = opFiles.ContainsKey(k1001) ? opFiles[k1001] : new QFile();

                    if (qf.Charactericstics.Count == 0)
                    {
                        opFiles.Add(k1001, qf);
                        qf[1001] = k1001;
                        qf[1002] = k1001;
                        qf[1086] = k1001;

                        // 4 -> 2 暂时只考虑扭距和角度
                        for (int i = 0; i < 2; i++)
                        {
                            var chi = qf.AddQCharacteristic();
                            chi[2001] = k2001s[i];
                            chi[2002] = k2002s[i];
                            chi[2110] = values[i * 3 + 0];
                            chi[2111] = values[i * 3 + 1];
                            chi[2142] = values[i * 3 + 2];
                        }
                    }

                    // 4 -> 2 暂时只考虑扭距和角度
                    for (int i = 0; i < 2; i++)
                    {
                        var chi = qf.Charactericstics[i];
                        var di = chi.AddItem();
                        di.SetValue(row[2 + i]);
                        di.date = dt;
                        di[0009] = k0009;
                        di[0010] = k0100; // 2021/12/29 更新 原为固定值 "1120071";
                        di[0012] = k0012;
                        di[0014] = k0014;
                        if (filenames.Count > 0)
                            di[0056] = filenames[i];
                    }
                }
                catch (Exception ex)
                {
                    Common.AddLog(ex.Message, LogType.Error);
                }
            }



            string outputidr = Path.GetFullPath(OutputDirectory);

            if (!Directory.Exists(outputidr))
            {
                Directory.CreateDirectory(outputidr);
                Console.WriteLine($"Directory '{outputidr}' is created.");
            }


            Console.WriteLine($"Save DFQ files to folder '{OutputDirectory}' count={opFiles.Values.Count}");

            foreach (QFile qf in opFiles.Values)
            {
                var dfqfile = Path.Combine(outputidr, $"CVINET_{qf[1001]}_{DateTime.Now:yyyyMMddHHmmss}.dfq");
                Console.WriteLine("Save dfq file to : " + dfqfile);
                SaveToDFQ(qf, dfqfile);
            }

            // 需要修改
            LastResID += BatchCount;
            dh[Config.LastResID] = LastResID.ToString();
            dh.Save();
        }

        internal double Convert1(string v)
        {
            var bts = new byte[8];
            for (int i = 0; i < v.Length / 2; i++)
                bts[i] = System.Convert.ToByte(v.Substring(i * 2, 2), 16);

            MemoryStream ms = new MemoryStream(bts);
            BinaryReader br = new BinaryReader(ms);
            var d = br.ReadDouble();
            br.Close();
            return d;
        }


        // 修改代码，现在临时从 opindices 中匹配，根据K1001和SpindleNumber来匹配OP索引
        private string GetK0100(string k1001, string spindleNumber)
        {
            var k0100 = k1001;

            // K0100的主要格式有两种：[DIFF1002R]@192.168.21.156 和 DCT-0225
            if (k1001.Contains("@"))
                k0100 = k1001.Split('@')[0];

            k0100 = k0100.Trim('[', ']');

            if (opindices.Count(op => (op[0].Contains(k0100) || k0100.Contains(op[0])) && op[2] == spindleNumber) > 0)
            {
                var row = opindices.First(op => op[0].Contains(k0100) && op[2] == spindleNumber);
                return row[3];
            }

            int pid = catlog.getCatalogPID("K4090", k0100);
            return pid < 0 ? "" : catlog.GetValue("K4091", pid);
        }



    }
}
